package com.zbycorp.generatecode.actions;

import com.intellij.database.model.DasColumn;
import com.intellij.database.psi.DbTable;
import com.intellij.database.util.DasUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.PsiElement;
import com.intellij.util.containers.JBIterable;
import com.intellij.util.ui.JBUI;
import com.zbycorp.generatecode.dict.GlobalDict;
import com.zbycorp.generatecode.entity.TypeMapper;
import com.zbycorp.generatecode.enums.MatchTypeEnum;
import com.zbycorp.generatecode.service.SettingsStorageService;
import com.zbycorp.generatecode.ui.SelectSavePath;
import com.zbycorp.generatecode.utils.CacheDataUtil;
import com.zbycorp.generatecode.utils.StringUtil;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;


/**
 * @author YCL
 * @date 2023/3/23
 */
public class GenerateCodeAction extends AnAction {

    private CacheDataUtil cacheDataUtil = CacheDataUtil.getInstance();

    @Override
    public void actionPerformed(AnActionEvent event) {
        Project project = event.getProject();
        if (project == null) {
            return;
        }
        cacheSelectDbTable(event);
        if (!typeValidator(project, cacheDataUtil.getSelectDbTable())) {
            return;
        }

        new SelectSavePath(project).show();
    }

    private void cacheSelectDbTable(AnActionEvent event) {
        //获取选中的PSI元素
        PsiElement psiElement = event.getData(LangDataKeys.PSI_ELEMENT);
        DbTable selectDbTable = null;
        if (psiElement instanceof DbTable) {
            selectDbTable = (DbTable) psiElement;
        }
        cacheDataUtil.setSelectDbTable(selectDbTable);
    }

    /**
     * 类型校验，如果存在未知类型则引导用户去选择
     *
     * @param project Project
     * @param dbTable 选中的表
     * @return 是否验证通过
     */
    private boolean typeValidator(Project project, DbTable dbTable) {
        JBIterable<? extends DasColumn> columns = DasUtil.getColumns(dbTable);
        List<TypeMapper> typeMapperList = SettingsStorageService.getSettingStorage(project).getTypeMapperList();

        // 简单的记录报错弹窗次数，避免重复报错
        Set<String> errorCount = new HashSet<>();

        FLAG:
        for (DasColumn column : columns) {
            String typeName = column.getDataType().getSpecification();
            for (TypeMapper typeMapper : typeMapperList) {
                try {
                    if (typeMapper.getMatchType() == MatchTypeEnum.ORDINARY) {
                        if (typeName.equalsIgnoreCase(typeMapper.getColumnType())) {
                            continue FLAG;
                        }
                    } else {
                        // 不区分大小写的正则匹配模式
                        boolean matches = Pattern.compile(typeMapper.getColumnType(), Pattern.CASE_INSENSITIVE).matcher(typeName).matches();
                        if (matches) {
                            continue FLAG;
                        }
                    }
                } catch (PatternSyntaxException e) {
                    if (!errorCount.contains(typeMapper.getColumnType())) {
                        Messages.showWarningDialog(
                                "类型映射《" + typeMapper.getColumnType() + "》存在语法错误，请及时修正。报错信息:" + e.getMessage(),
                                GlobalDict.TITLE_INFO
                        );
                        errorCount.add(typeMapper.getColumnType());
                    }
                }
            }
            // 没找到类型，提示用户选择输入类型
            new Dialog(project, typeName).showAndGet();
        }
        return true;
    }

    public static class Dialog extends DialogWrapper {

        private Project project;
        private String typeName;

        private JPanel mainPanel;

        private ComboBox<String> comboBox;

        protected Dialog(@Nullable Project project, String typeName) {
            super(project);
            this.project = project;
            this.typeName = typeName;
            this.initPanel();
        }

        private void initPanel() {
            setTitle(GlobalDict.TITLE_INFO);
            String msg = String.format("数据库类型%s，没有找到映射关系，请输入想转换的类型？", typeName);
            JLabel label = new JLabel(msg);
            this.mainPanel = new JPanel(new BorderLayout());
            this.mainPanel.setBorder(JBUI.Borders.empty(5, 10, 7, 10));
            mainPanel.add(label, BorderLayout.NORTH);
            this.comboBox = new ComboBox<>(GlobalDict.DEFAULT_JAVA_TYPE_LIST);
            this.comboBox.setEditable(true);
            this.mainPanel.add(this.comboBox, BorderLayout.CENTER);
            init();
        }

        @Override
        protected @Nullable JComponent createCenterPanel() {
            return this.mainPanel;
        }

        @Override
        protected void doOKAction() {
            super.doOKAction();
            String selectedItem = (String) this.comboBox.getSelectedItem();
            if (StringUtil.isEmpty(selectedItem)) {
                return;
            }
            TypeMapper typeMapper = new TypeMapper();
            typeMapper.setMatchType(MatchTypeEnum.ORDINARY);
            typeMapper.setJavaType(selectedItem);
            typeMapper.setColumnType(typeName);
            SettingsStorageService.getSettingStorage(this.project).getTypeMapperList().add(typeMapper);
        }
    }

}
